#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         AssessmentComponentState.py
#
# Copyright:    Copyright (c) 2004, Faulkner Technologies
#
# Author:       Brian Oliver
#
# Description:  Instances of the AssessmentComponentState class
#               store/represent the state of individual components
#               within an assessment in a storage-agnostic manner.
#               
#               Collections of AssessmentComponentStates are managed
#               by instances of the Assessment class!
#
# See Also:     Assessment, Assessible, AssessmentComponentValueTypes
#               and AssessmentStorageService
#####################################################################

#####################################################################
## KnowledgeEngine Library Imports
from Common import *

#####################################################################
## Zope Library Imports
from Globals import InitializeClass
from AccessControl import ClassSecurityInfo
from AccessControl.Role import RoleManager
from DateTime import DateTime
 
#####################################################################
## Python Library Imports
# (None)

#####################################################################
## AssessmentComponentState Class Definition
class AssessmentComponentState(RoleManager):
    """
        An in-memory storage-agnostic representation of the
        assessment state for an individual component
    """
        
    #---------------------------------------------------------------#

    #declare security so ClassInfo may be accessed in DTML/ZPT etc
    security = ClassSecurityInfo()
    security.declareObjectPublic()
    security.setDefaultAccess("allow")

    #---------------------------------------------------------------#

    def __init__(self, assessmentIdentity, modelIdentity, componentIdentity, valueType, value, searchIndex=None, searchValue=None, revision=None):
        """
            New AssessmentComponentState is constructed using using four properties;
            * The identity of the assessment (String)
            * The model identity to which the state pertains (String)
            * The component identity to which the state pertains (String)
            * The type of the value that will be stored (String)
            * The value (Polymorhic)
        """
               
        ### the following attributes are generally stored together (and need to be persisted)
        self.assessmentIdentity = assessmentIdentity
        self.modelIdentity = modelIdentity
        self.componentIdentity = componentIdentity
        self.instantCreated = DateTime()
        self.instantModified = DateTime()
        self.modifiedByUser = None
        self.isNew = true
        self.isModified = true
        self.value = value

        self.searchIndex = searchIndex
        self.searchValue = searchValue
        
        self.revision = revision

        ### the following values need not be stored 
        #the valueType is derived from the component using the Assessible.getAssessmentValueType() method
        self.valueType = valueType                  #(String) see AssessmentComponentValueTypes for defined constants

    #---------------------------------------------------------------#
    
    def getRevision(self):
        """
           Returns the current component state revision
        """
        
        if self.revision is None: return None
        
        return int(self.revision)
        
    #---------------------------------------------------------------#

    def setRevision(self, revision):
        """
            Sets the assessment component state revision.
        """
        
        self.revision = revision


    #---------------------------------------------------------------#

    def getAssessmentIdentity(self):
        """
            Returns the unique identity for the assessment that owns the state
            RETURN TYPE: String
        """
        
        return self.assessmentIdentity

    #---------------------------------------------------------------#

    def getModelIdentity(self):
        """
            Returns the unique identity for the model that owns the state
            RETURN TYPE: String
        """
        
        return self.modelIdentity

    #---------------------------------------------------------------#

    def getComponentIdentity(self):
        """
            Returns the identity of the component that owns the state
            RETURN TYPE: String
        """
        
        return self.componentIdentity

    #---------------------------------------------------------------#

    def getInstantCreated(self):
        """
            Returns the instant in time (as a DateTime) that the state was created
            
            RETURN TYPE: DateTime
        """

        return self.instantCreated

    #---------------------------------------------------------------#

    def setInstantCreated(self, instantCreated):
        """
            Sets the instant in time (as a DateTime) that the state was created
        """

        self.instantCreated = instantCreated

    #---------------------------------------------------------------#

    def getInstantModified(self):
        """
            Returns the instant in time (as a DateTime) that the state was modified
            
            RETURN TYPE: DateTime
        """

        return self.instantModified

    #---------------------------------------------------------------#

    def setInstantModified(self, instantModified):
        """
            Sets the instant in time (as a DateTime) that the state was modified
        """

        self.instantModified = instantModified

    #---------------------------------------------------------------#

    def getModifiedByUser(self):
        """
            Return the user identity of the user who last modified this
            component.
        """

        return self.modifiedByUser

    #---------------------------------------------------------------#

    def setModifiedByUser(self, userIdentity):
        """
            Sets the user who last modified the state of this component
        """

        # Do nothing if the old and new values are identical
        if userIdentity == self.getModifiedByUser():
            return

        self.modifiedByUser = userIdentity

    #---------------------------------------------------------------#

    def getIsNew(self):
        """
            Returns if the component state is new (not yet persisted)
            
            RETURN TYPE: Boolean
        """

        return self.isNew

    #---------------------------------------------------------------#

    def setIsNew(self, isNew):
        """
            Sets if the component state is new (not yet persisted)
        """

        self.isNew = isNew

    #---------------------------------------------------------------#

    def getIsModified(self):
        """
            Returns if the component state has been modified since created or loaded 
            
            RETURN TYPE: Boolean
        """

        return self.isModified

    #---------------------------------------------------------------#

    def setIsModified(self, isModified):
        """
            Sets if the component state has been modified since created or loaded 
        """

        self.isModified = isModified

    #---------------------------------------------------------------#

    def getValueType(self):
        """
            Returns the type of the value that is store with this state
            
            NOTE: See AssessmentComponentValueTypes for a list of defined contants            
            
            RETURN TYPE: String
        """

        return self.valueType

    #---------------------------------------------------------------#

    def getValue(self):
        """
            Returns the value of the component state
            RETURN TYPE: Polymorphic
        """

        return self.value

    #---------------------------------------------------------------#

    def setValue(self, newValue):
        """
            Sets the value of the component state
        """

        #print "AssessmentComponentState(%s): %s -> %s" % (self.getComponentIdentity(), self.getValue(), newValue)

        # Don't mark as changed if the saved value is the same.
        if newValue == self.getValue():
            return 

        self.value = newValue
        self.setIsModified(true)


    #---------------------------------------------------------------#
                
    def setSearchIndex(self, value):
        """
            Sets the search index
        """

        self.searchIndex = value
        #self.isModified  = true
        
    #---------------------------------------------------------------#
    
    def getSearchIndex(self):
        """ 
            Gets the search index
        """
        
        # Use getattr for backwards compat (Avoid AttributeError on older objects)
        return getattr(self, 'searchIndex', '')
    
    #---------------------------------------------------------------#
    
    def setSearchValue(self, value):
        """
            Sets the search index
        """
        
        self.searchValue = value
        #self.isModified  = true
        
    #---------------------------------------------------------------#
    
    def getSearchValue(self):
        """ 
            Gets the search index
        """
        
        # Use getattr for backwards compat (Avoid AttributeError on older objects)
        return getattr(self, 'searchValue', '')
    
    #---------------------------------------------------------------#    
    
    
    
    
    
                
#####################################################################
## Class Initialisation
InitializeClass(AssessmentComponentState)
